import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ImageUtil {
  static Future<ImageInfo> load(
    BuildContext context,
    ImageProvider provider, {
    Size size,
  }) {
    final ImageConfiguration config =
        createLocalImageConfiguration(context, size: size);
    final Completer<ImageInfo> completer = Completer<ImageInfo>();
    final ImageStream stream = provider.resolve(config);
    ImageStreamListener listener;
    listener = ImageStreamListener(
      (ImageInfo image, bool sync) {
        stream.removeListener(listener);
        completer.complete(image);
      },
      onError: (dynamic exception, StackTrace stackTrace) {
        provider.obtainKey(config).then((key) {
          PaintingBinding.instance.imageCache.evict(key);
        });
        completer.completeError(exception, stackTrace);
        stream.removeListener(listener);
      },
    );
    stream.addListener(listener);
    return completer.future;
  }

  static Future<ui.Image> loadImage(
    BuildContext context,
    ImageProvider provider, {
    Size size,
  }) {
    final ImageConfiguration config =
        createLocalImageConfiguration(context, size: size);
    final Completer<ui.Image> completer = Completer<ui.Image>();
    final ImageStream stream = provider.resolve(config);
    ImageStreamListener listener;
    listener = ImageStreamListener(
      (ImageInfo image, bool sync) {
        stream.removeListener(listener);
        completer.complete(image.image);
      },
      onError: (dynamic exception, StackTrace stackTrace) {
        provider.obtainKey(config).then((key) {
          PaintingBinding.instance.imageCache.evict(key);
        });
        completer.completeError(exception, stackTrace);
        stream.removeListener(listener);
      },
    );
    stream.addListener(listener);
    return completer.future;
  }

  static Future<Uint8List> loadBytes(
    BuildContext context,
    ImageProvider provider, {
    Size size,
  }) async {
    final ImageConfiguration config =
        createLocalImageConfiguration(context, size: size);
    final Completer<ImageInfo> completer = Completer<ImageInfo>();
    final ImageStream stream = provider.resolve(config);
    ImageStreamListener listener;
    listener = ImageStreamListener(
      (ImageInfo image, bool sync) {
        stream.removeListener(listener);
        completer.complete(image);
      },
      onError: (dynamic exception, StackTrace stackTrace) {
        provider.obtainKey(config).then((key) {
          PaintingBinding.instance.imageCache.evict(key);
        });
        completer.completeError(exception, stackTrace);
        stream.removeListener(listener);
      },
    );
    stream.addListener(listener);
    ImageInfo imageInfo = await completer.future;
    ui.Image image = imageInfo.image;
    ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    return byteData.buffer.asUint8List();
  }
}
